package com.nineclock.attendance.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nineclock.attendance.dto.AttendGroupDTO;
import com.nineclock.attendance.dto.AttendGroupPCExtraConfigDTO;
import com.nineclock.attendance.dto.AttendGroupPartDTO;
import com.nineclock.attendance.enums.AttendEnums;
import com.nineclock.attendance.mapper.AttendGroupMapper;
import com.nineclock.attendance.mapper.AttendGroupPartMapper;
import com.nineclock.attendance.pojo.AttendGroup;
import com.nineclock.attendance.pojo.AttendGroupPart;
import com.nineclock.attendance.service.AttendGroupService;
import com.nineclock.common.entity.PageResult;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.threadlocal.CurrentUserHolder;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.system.feign.SysOrganizationFeign;
import com.nineclock.system.feign.SysUserFeign;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@Transactional
public class AttendGroupServiceImpl implements AttendGroupService {
    @Autowired
    private AttendGroupPartMapper attendGroupPartMapper;
    @Autowired
    private SysOrganizationFeign organizationFeign;
    @Autowired
    private AttendGroupMapper attendGroupMapper;
    /**
     * 考勤组: 分页查询
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PageResult<AttendGroupDTO> queryAttendGroupPage(Integer page, Integer pageSize) {
        LambdaQueryWrapper<AttendGroup> attendGroupQw=new LambdaQueryWrapper<>();

        attendGroupQw.eq(AttendGroup::getCompanyId, CurrentUserHolder.get().getCompanyId());

        Integer count = attendGroupMapper.selectCount(attendGroupQw);

        if (count == 0) {
            AttendGroup attendGroup=this.buildDefaultAttendGroup();

            attendGroupMapper.insert(attendGroup);

            List<Long> ids = organizationFeign.queryDepartmentIds().getData();
            for (Long departmentId : ids) {
                AttendGroupPart attendGroupPart=new AttendGroupPart();

                attendGroupPart.setAttendGroupId(attendGroup.getId());
                attendGroupPart.setObjectId(departmentId);
                attendGroupPart.setAttendType(AttendEnums.ATTEND_TYPE_YES.value());
                attendGroupPart.setObjectType(AttendEnums.ATTEND_OBJECT_TYPE_DEP.value());

                attendGroupPartMapper.insert(attendGroupPart);
            }
        }

        Page<AttendGroup> p=new Page<>();
         p = attendGroupMapper.selectPage(p, attendGroupQw);
        List<AttendGroup> records = p.getRecords();
        List<AttendGroupDTO> attendGroupDTOS = BeanHelper.copyWithCollection(records, AttendGroupDTO.class);

        attendGroupDTOS.forEach(attendGroupDTO -> {
            LambdaQueryWrapper<AttendGroupPart> attendGroupPartQW=new LambdaQueryWrapper<>();
//            attendGroupPartQW.eq(AttendGroupPart::getAttendGroupId,CurrentUserHolder.get().getCompanyId());
            attendGroupPartQW.eq(AttendGroupPart::getAttendGroupId,attendGroupDTO.getId());
            attendGroupPartQW.eq(AttendGroupPart::getAttendType,AttendEnums.ATTEND_TYPE_YES.value());
            List<AttendGroupPart> parts = attendGroupPartMapper.selectList(attendGroupPartQW);

            //获取参与者为部门ID集合
            List<Long> departmentIds = parts.stream().filter(attendGroupPart -> {
                return attendGroupPart.getObjectType() == AttendEnums.ATTEND_OBJECT_TYPE_DEP.value();
            }).map(attendGroupPart -> {
                return attendGroupPart.getObjectId();
            }).collect(Collectors.toList());
            //获取参与者为用户ID集合
            List<Long> userIds = parts.stream().filter(attendGroupPart -> {
                return attendGroupPart.getObjectType() == AttendEnums.ATTEND_OBJECT_TYPE_USER.value();
            }).map(attendGroupPart -> {
                return attendGroupPart.getObjectId();
            }).collect(Collectors.toList());

            Integer depMemberCount=0;
            if (CollectionUtil.isNotEmpty(departmentIds)){
                depMemberCount=organizationFeign.queryUserCountByDepartmentIds(departmentIds).getData();
            }
            Integer totalCount = depMemberCount + userIds.size();
            attendGroupDTO.setMemberNum(totalCount);
        });

        PageResult<AttendGroupDTO> pageResult = new PageResult<>(p.getTotal(), p.getPages(), attendGroupDTOS);

        return pageResult;
    }

    /**
     * 保存考勤组数据
     * @param attendGroupDTO
     */
    @Override
    public void addAttendGroup(AttendGroupDTO attendGroupDTO) {
        //健壮性判断
        if(attendGroupDTO == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        AttendGroup attendGroup = BeanHelper.copyProperties(attendGroupDTO, AttendGroup.class);

        //设置考勤组关联的企业ID
        attendGroup.setCompanyId(CurrentUserHolder.get().getCompanyId());
        attendGroup.setCreateUserId(CurrentUserHolder.get().getCompanyUserId());
        attendGroup.setUpdateUserId(CurrentUserHolder.get().getCompanyUserId());

        //工作日, 使用逗号 "," 分割
        if(attendGroupDTO.getWorkdays() != null){
            attendGroup.setWorkdays(StrUtil.join(",", attendGroupDTO.getWorkdays().toArray()));
        }


        //必须/不用打卡的日期 ----> 获取出来之后使用逗号","拼接
        List<String> necessaryTimeList = new ArrayList<>();
        List<String> unnecessaryTimeList = new ArrayList<>();

        List<AttendGroupPCExtraConfigDTO> extraConfigDTOList = attendGroupDTO.getExtraConfig();
        for (AttendGroupPCExtraConfigDTO extraConfigDTO : extraConfigDTOList) {
            String time = extraConfigDTO.getSetDate();
            String date = DateUtil.format(new Date(Long.valueOf(time)), "yyyy-MM-dd");

            if(extraConfigDTO.getRequiredAttend() == 1){
                necessaryTimeList.add(date);
            }else if(extraConfigDTO.getRequiredAttend() == 0){
                unnecessaryTimeList.add(date);
            }
        }

        attendGroup.setNecessaryTimeList(StrUtil.join(",", necessaryTimeList.toArray()));
        attendGroup.setUnnecessaryTimeList(StrUtil.join(",",unnecessaryTimeList.toArray()));

        //保存考勤组
        attendGroupMapper.insert(attendGroup);

        this.saveAttendGroupPart(attendGroupDTO, attendGroup);
    }

    @Autowired
    SysUserFeign userFeign;
    /**
     *  根据用户ID获取考勤组信息
     * @return
     */
    @Override
    public AttendGroupDTO getAttendGroupByUserId() {
        Long companyUserId = CurrentUserHolder.get().getCompanyUserId();
        AttendGroupPart attendGroupPart=this.getAttendGroupPart(companyUserId,AttendEnums.ATTEND_OBJECT_TYPE_USER.value());

        if (attendGroupPart == null) {
            List<Long> departmentIds = userFeign.queryDepartmentsByUserId(companyUserId).getData();
            if(CollectionUtil.isNotEmpty(departmentIds)){
                for (Long departmentId : departmentIds) {
                    attendGroupPart = this.getAttendGroupPart(departmentId, AttendEnums.ATTEND_OBJECT_TYPE_DEP.value());
                    if(attendGroupPart != null){
                        break;
                    }
                }
            }
        }
        if(attendGroupPart != null){
            //查询考勤组对象
            AttendGroup attendGroup = attendGroupMapper.selectById(attendGroupPart.getAttendGroupId());

            //转换为dto数据
            AttendGroupDTO attendGroupDTO = BeanHelper.copyProperties(attendGroup, AttendGroupDTO.class);
            //1,0,1,0,1,0,0
            String workdays = attendGroup.getWorkdays();
            String[] split = workdays.split(",");
            List<String> workdayList = Arrays.asList(split);

            attendGroupDTO.setWorkdays(workdayList);

            return attendGroupDTO;
        }
        return null;
    }

    /**
     *  查询当前用户的考勤组
     * @param companyId
     * @param value
     * @return
     */
    private AttendGroupPart getAttendGroupPart(Long companyUserId, int type) {
        LambdaQueryWrapper<AttendGroupPart> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AttendGroupPart::getObjectType, type);
        wrapper.eq(AttendGroupPart::getObjectId, companyUserId);

        AttendGroupPart attendGroupPart = attendGroupPartMapper.selectOne(wrapper);
        return attendGroupPart;
    }

    //关联用户, 部门到该考勤组
    private void saveAttendGroupPart(AttendGroupDTO attendGroupDTO, AttendGroup attendGroup) {
        //需要参加考勤组的处理
        List<AttendGroupPartDTO> participates = attendGroupDTO.getParticipates();
        //先删除部门或者用户与考勤组的关系， 添加新的关系
        participates.forEach(attendGroupPartDTO -> {
            LambdaQueryWrapper<AttendGroupPart> attendGroupPartQw = new LambdaQueryWrapper<>();
            attendGroupPartQw.eq(AttendGroupPart::getObjectType, attendGroupPartDTO.getObjectType());
            attendGroupPartQw.eq(AttendGroupPart::getObjectId, attendGroupPartDTO.getObjectId());

            attendGroupPartMapper.delete(attendGroupPartQw);

            //删除后添加新的关系
            AttendGroupPart attendGroupPart = new AttendGroupPart();
            attendGroupPart.setAttendGroupId(attendGroup.getId());
            attendGroupPart.setAttendType(AttendEnums.ATTEND_TYPE_YES.value());
            attendGroupPart.setObjectType(attendGroupPartDTO.getObjectType());
            attendGroupPart.setObjectId(attendGroupPartDTO.getObjectId());

            attendGroupPartMapper.insert(attendGroupPart);
        });

        //不需要参加考勤组的处理
        List<AttendGroupPartDTO> notParticipates = attendGroupDTO.getNotParticipates();
        //先删除部门或者用户与考勤组的关系， 添加新的关系
        notParticipates.forEach(attendGroupPartDTO -> {
            LambdaQueryWrapper<AttendGroupPart> attendGroupPartQw = new LambdaQueryWrapper<>();
            attendGroupPartQw.eq(AttendGroupPart::getObjectType, attendGroupPartDTO.getObjectType());
            attendGroupPartQw.eq(AttendGroupPart::getObjectId, attendGroupPartDTO.getObjectId());
            //删除关系
            attendGroupPartMapper.delete(attendGroupPartQw);

            //删除后添加新的关系
            AttendGroupPart attendGroupPart = new AttendGroupPart();
            attendGroupPart.setAttendGroupId(attendGroup.getId());
            attendGroupPart.setAttendType(AttendEnums.ATTEND_TYPE_NO.value());
            attendGroupPart.setObjectType(attendGroupPartDTO.getObjectType());
            attendGroupPart.setObjectId(attendGroupPartDTO.getObjectId());

            attendGroupPartMapper.insert(attendGroupPart);
        });
    }
    /**
     * 构建默认的考勤组
     * @return
     */
    private AttendGroup buildDefaultAttendGroup() {
        AttendGroup attendGroup = new AttendGroup();
        attendGroup.setName("默认考勤组");
        attendGroup.setCreateUserId(CurrentUserHolder.get().getCompanyUserId());
        attendGroup.setAddressRange(400);
        attendGroup.setAllowLateMinutes(10);
        attendGroup.setCompanyId(CurrentUserHolder.get().getCompanyId());
        attendGroup.setCreateTime(new Date());
        attendGroup.setLat(new Double("108.88995700000000000000"));
        attendGroup.setLng(new Double("34.37182600000000000000"));
        attendGroup.setStartWorkTime("09:00:00");
        attendGroup.setOffWorkTime("18:00:00");
        attendGroup.setStartNoonRestTime("12:00:00");
        attendGroup.setEndNoonRestTime("14:00:00");
        attendGroup.setLateMinutes(30);
        attendGroup.setWorkdays("1,1,1,1,1,0,0");
        return attendGroup;
    }
}
